import { useBoolean, useRequest, useSet, useSetState } from 'ahooks';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { currentConsoltDoctor, getChathistoryList, sendMessage } from '../../../api/con';
import style from './style.module.scss';
import { WdHeader } from '../../../components';
import { Input, Button, Notify, Tag, Popup, Dialog, Loading } from 'react-vant'
import OSS from 'ali-oss';
import { emojiList, reaplceEmojiToString, replaceStringToEmoji } from '../../../emoji';
import { useSelector } from 'react-redux';
import { useAppSelector } from '../../../app/hooks';
// import { useDoctorAwser } from './hooks';

interface DoctorState {
  recordId: number //	问诊id
  doctorId: number //	医生id
  imagePic: string	// 	医生形象照
  doctorName: string //	string	医生姓名
  department: string	// string	科室
  jobTitle: string	 // string	职称
  evaluateStatus: number //	评价状态
  userName: string	// string	医生极光IM账户
  jiGuangPwd: string	 //string	医生极光密码
  inquiryTime: string  // long	问诊时间
}
interface MedState { type: string, url: string }

interface HistoryListState {
  askTime: number
  content: string | MedState
  direction: number
  doctorHeadPic: string
  msgType: number
  userHeadPic: string
  state: 'success' | 'loading' | 'fail'
}
const ws = new WebSocket('ws://localhost:7000');
let inquiryId = 0;
const Index: React.FC = () => {
  // const { doctorAwser } = useDoctorAwser()
  const headPic = useAppSelector(state => state.user.userInfo.headPic)
  const scrollEl = useRef<HTMLDivElement | null>(null)
  // 当前正在聊的医生
  const { data: doctor = {} as DoctorState } = useRequest(async () => {
    const resp = await currentConsoltDoctor();
    setParams({
      inquiryId: resp.data.result.recordId,
      doctorId: resp.data.result.doctorId,
    })
    setHistoryParam({
      inquiryId: resp.data.result.recordId,
      count: 20,
      page: 1
    })
    inquiryId = resp.data.result.recordId
    return resp.data.result as DoctorState
  })
  // 发送消息 的请求参数
  const [params, setParams] = useSetState({
    inquiryId: 0,
    // 原来字符串
    content: '',
    type: 1,
    doctorId: 0
  })

  // 转换表情之后的内容
  const content = useMemo(() => {
    return replaceStringToEmoji(params.content)
  }, [params.content])
  // 发送消息函数
  const send = async (param = params, isClear = true, loading = true) => {
    return new Promise(async (resolve, reject) => {
      // 判断是不是有网络
      if (!window.navigator.onLine) {
        Notify.show({ type: 'danger', message: "网络异常，请检查网络" });
        handleNetwordUutline()
        reject('网络异常，请检查网络')
        return
      }
      // 是否loading
      if (loading) {
        const data = historyList.concat({
          "askTime": new Date().getTime(),
          "content": content,
          "direction": 1,
          "msgType": 1,
          "userHeadPic": headPic,
          state: 'loading'
        } as HistoryListState);
        setHistoryList(data)
      }
      // 发送消息
      const resp = await sendMessage(param);
      if (resp.data.status === '0000') {
        if (isClear) {
          setParams({
            content: ''
          })
        }
        resolve('ok')
        ws.send(JSON.stringify({ type: 'updateChatHistory' }))
      }
    })
  }
  // 断网处理
  const handleNetwordUutline = () => {
    // 断网处理
    // 0. 聊天的信息  和 聊天列表一致
    // 1. 将聊天的信息存储到本地存储
    const info = {
      "askTime": new Date().getTime(),
      "content": content,
      "direction": 1,
      "msgType": 1,
      "userHeadPic": headPic,
      state: 'fail'
    }
    setLocalHistoryList(localHistoryList.concat(info as HistoryListState));
    params.content = ''
  }
  // 发送曾经失败的消息
  const sendFailMesage = (item: HistoryListState) => {
    Dialog.confirm({
      title: '提示',
      message: '是否重新发送失败的消息',
    })
      .then(() => {
        if (!window.navigator.onLine) {
          Notify.show({ type: 'danger', message: "网络异常，请检查网络" });
          return
        }
        send({
          ...params,
          content: item.content.toString()
        }).then(() => {
          // 清除存储
          const data = localHistoryList.filter(v => v.askTime !== item.askTime)
          setLocalHistoryList(data)
        })
      })
      .catch(() => { })
  }

  // 请求历史记录参数
  const [historyParam, setHistoryParam] = useState({
    inquiryId: 0,
    count: 20,
    page: 1
  })

  // 服务器聊天记录
  const [historyList, setHistoryList] = useState<HistoryListState[]>([])
  // 失败的消息=记录
  const [localHistoryList, setLocalHistoryList] = useState<HistoryListState[]>(JSON
    .parse(localStorage.getItem('localHistoryList') || '[]'))
  // 合并消息
  const mergeMessageList = useMemo(() => {
    // 合并消息
    return historyList.concat(localHistoryList).sort((a, b) => {
      // 排序 按照事件升序
      return a.askTime - b.askTime
    }).map(v => {
      // 数据处理
      try {
        const data = JSON.parse(v.content as string);
        // 输入的是数字
        if (typeof data === 'number') return v
        // 输入一个表情
        if (Array.isArray(data)) return v
        v.content = data
        return v
      } catch {
        return v
      }
    })

    // resp.data.result.reverse().map(v => {
    //   try {
    //     const data = JSON.parse(v.content);
    //     // 输入的是数字
    //     if (typeof data === 'number') return v
    //     // 输入一个表情
    //     if (Array.isArray(data)) return v
    //     v.content = data
    //     return v
    //   } catch {
    //     return v
    //   }

    // })
  }, [historyList, localHistoryList])

  // 请求函数历史记录参数
  const getHistoryList = async () => {
    const resp = await getChathistoryList({ ...historyParam, inquiryId });
    setHistoryList(resp.data.result)
  }

  // 监听服务器发送消息给客户端
  useEffect(() => {

    ws.addEventListener('message', ({ data }) => {
      const result = JSON.parse(data);
      if (result.type === 'getChatHistory') {
        getHistoryList()
      }
    })
  }, [])
  // 默认获取聊天记录
  useEffect(() => {
    historyParam.inquiryId && getHistoryList()
  }, [historyParam])

  // 每次有消息 ， 滚动条到底部
  useEffect(() => {
    if (scrollEl.current)
      scrollEl.current.scrollTop = 10000000
  }, [mergeMessageList])

  // 失败的消息存储到本地
  useEffect(() => {
    localStorage.setItem('localHistoryList', JSON.stringify(localHistoryList))
  }, [localHistoryList])

  /********************************** 发送媒体 ******************************************/
  const inputRef = useRef<HTMLInputElement | null>(null)
  const hnadleClickInput = () => inputRef.current?.click();
  const uploadImage = async () => {

    const input = inputRef.current as HTMLInputElement;
    const files = input.files as FileList
    const file = files[0] as File
    if (!file.type.includes('image') && !file.type.includes('video')) {
      Notify.show({ type: 'danger', message: '只允许发送的媒体是图片或者视频' })
      return;
    }
    if (file.size > 1024 * 1024 * 50) {
      Notify.show({ type: 'danger', message: '媒体最大不可以超过50MB' })
      return;
    }
    const type = file.type.includes('image') ? 'image' : 'video'


    if (type === 'image') {
      const fileReader = new FileReader();
      fileReader.readAsDataURL(file);
      fileReader.addEventListener('load', () => {
        // loading
        const dataMessage = historyList.concat({
          "askTime": new Date().getTime(),
          "content": JSON.stringify({ type: type, url: fileReader.result as string }),
          "direction": 1,
          "msgType": 1,
          "userHeadPic": headPic,
          state: 'loading'
        } as HistoryListState);
        setHistoryList(dataMessage)
      })
    }

    if (type === 'video') {

    }

    // 发送 oss
    // 1. 创建 oss 实例
    const client = new OSS({
      region: 'oss-cn-shanghai',
      accessKeyId: 'LTAI5tEF6SXY58gNaKQsZcxD',
      accessKeySecret: 'KUwe276Rg8uWGUWyoIDLlaSjzCJZLH',
      bucket: 'wd-lt',
    })
    // 2. 上传 媒体
    const resp = await client.put(file.name, file)
    // 3. 媒体路径
    const data = { type: type, url: resp.url };
    const content = JSON.stringify(data);
    send({ ...params, content: content }, false, false)
  }
  /********************************** 发送表情 ******************************************/
  const [showEmoji, { setTrue, setFalse }] = useBoolean(false);
  const addEmojiToContent = (v: { rule: string, content: string }) => {
    setFalse();
    setParams({
      content: params.content + v.rule
    })
  }

  return (
    <div>
      <input type="file" style={{ display: 'none' }} ref={inputRef} onChange={uploadImage} />
      <WdHeader mode='black' title={doctor.doctorName}></WdHeader>
      <div className={style.chat_list} ref={scrollEl}>
        {
          mergeMessageList.map((item, index) => {
            const listClassName = item.direction === 1 ? style.right : style.left
            const avatarUrl = item.direction === 1 ? item.userHeadPic : item.doctorHeadPic

            // 本文
            const CustomText = () => <>
              <CustomExclamation></CustomExclamation>
              <span>{replaceStringToEmoji(item.content)}</span>
            </>
            // 图片
            const CustomImage = () => <>
              <CustomExclamation></CustomExclamation>
              <img className={style.list_image} src={(item.content as MedState).url} alt="" />
            </>
            // 视频
            const CustomVidio = () => <>
              <CustomExclamation></CustomExclamation>
              <video className={style.list_image} controls src={(item.content as MedState).url}></video>
            </>
            // 感叹号 || loading
            const CustomExclamation = () => <div className={style.prefix}>
              {
                item.state === 'fail' && <span onClick={() => sendFailMesage(item)} style={{ color: 'red', fontWeight: 'bold' }}>!</span>
              }

              {
                item.state === 'loading' && <Loading></Loading>
              }
            </div>
            return (
              <div key={index}>
                {
                  <div className={listClassName}>
                    <img src={avatarUrl} alt="" className={style.avator} />
                    <div className={style.content}>
                      {
                        typeof item.content === 'string'
                          ? <CustomText></CustomText>
                          : (item.content.type === 'image' ? <CustomImage></CustomImage> : <CustomVidio></CustomVidio>)
                      }
                    </div>

                  </div>
                }
                {/* {
                  item.direction === 2 && <div className={style.left}>
                    <img src={item.doctorHeadPic} alt="" className={style.avator} />
                    <div className={style.content}>
                      {typeof item.content === 'string'
                        ? <span>{item.content}</span>
                        : (item.content.type === 'image' ? <img className={style.list_image} src={item.content.url} alt="" /> : <video controls src={item.content.url}></video>)
                      }
                    </div>
                  </div>
                } */}
              </div>
            )
          })
        }

      </div>
      <div className={style.btm}>
        <Input placeholder='请发送消息' className={style.input} value={content} onChange={value => setParams({ content: reaplceEmojiToString(value) })} onKeyDown={e => e.keyCode === 13 && send().catch(() => ({}))}></Input>
        <div className={style.emjio} onClick={() => setTrue()}>😊</div>
        <Button type="primary" className={style.btn} onClick={() => hnadleClickInput()}>+</Button>
      </div>

      <Popup visible={showEmoji} onClose={() => setFalse()} position="bottom">
        <div style={{ padding: '10px 10px' }}>
          <h3>请选择表情：</h3>
          <div className={style.emoji_list}>
            {
              emojiList.map((v, i) => {
                return <span key={i} className={style.emoji_item} onClick={() => addEmojiToContent(v)}>{v.content}</span>
              })
            }
          </div>
        </div>

      </Popup>
    </div>
  )
}

export default Index

{/* <div className={style.left}>
<img src="https://wx2.sinaimg.cn/mw690/af6f43e2gy1hnhapc3t4xj218w0u0dmb.jpg" alt="" className={style.avator} />
<div className={style.content}>
  放弃哦哪里玩当前难为情去晚了；名单去晚了噩梦的期望去我去
  放弃哦哪里玩当前难为情去晚了；名单去晚了噩梦的期望去我去 放弃哦哪里玩当前难为情去晚了；名单去晚了噩梦的期望去我去
</div>
</div>
<div className={style.right}>
<img src="https://wx2.sinaimg.cn/mw690/af6f43e2gy1hnhapc3t4xj218w0u0dmb.jpg" alt="" className={style.avator} />
<div className={style.content}>
  放弃哦哪里玩当前难为情去晚了；名单去晚了噩梦的期望去我去 放弃哦哪里玩当前难为情去晚了；名单去晚了噩梦的期望去我去 放弃哦哪里玩当前难为情去晚了；名单去晚了噩梦的期望去我去 放弃哦哪里玩当前难为情去晚了；名单去晚了噩梦的期望去我去
</div>
</div>
<div className={style.time}>上午 11:20</div> */}